from django import forms
from .models import Code, CodeVersion, CodeFile
import os


class CodeForm(forms.ModelForm):
    """代码基本信息表单"""

    class Meta:
        model = Code
        fields = ["title", "description", "language", "is_public"]
        widgets = {
            "title": forms.TextInput(attrs={"class": "form-control", "placeholder": "请输入项目名称"}),
            "description": forms.Textarea(attrs={"class": "form-control", "rows": 4, "placeholder": "请输入项目描述"}),
            "language": forms.Select(attrs={"class": "form-select"}),
            "is_public": forms.CheckboxInput(attrs={"class": "form-check-input"}),
        }


class CodeVersionForm(forms.ModelForm):
    """代码版本表单"""

    commit_message = forms.CharField(
        max_length=200,
        required=False,
        widget=forms.TextInput(attrs={"placeholder": "版本说明（可选）"}),
        help_text="简要描述此版本的变更内容",
    )

    class Meta:
        model = CodeVersion
        fields = ["content", "commit_message"]
        widgets = {
            "content": forms.Textarea(
                attrs={"class": "code-editor", "rows": 20, "spellcheck": "false"}
            ),
        }

    def clean_content(self):
        """验证代码内容"""
        content = self.cleaned_data.get("content")

        # 检查代码大小
        if content:
            size_bytes = len(content.encode("utf-8"))
            max_size = 100 * 1024  # 100KB

            if size_bytes > max_size:
                raise forms.ValidationError(
                    f"代码大小超过限制（{size_bytes / 1024:.1f}KB，最大允许100KB）"
                )

        return content


class MultipleFileInput(forms.ClearableFileInput):
    """支持多文件上传的自定义输入组件"""

    allow_multiple_selected = True

    def __init__(self, attrs=None):
        if attrs is None:
            attrs = {}
        attrs["multiple"] = True
        super().__init__(attrs)


class MultipleFileField(forms.FileField):
    """支持多文件上传的自定义字段"""

    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", MultipleFileInput())
        super().__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        single_file_clean = super().clean
        if isinstance(data, (list, tuple)):
            result = []
            for d in data:
                if d:  # 只处理非空文件
                    cleaned_file = single_file_clean(d, initial)
                    if cleaned_file:
                        result.append(cleaned_file)
            return result
        else:
            result = single_file_clean(data, initial)
            return result if result else []


class MultiFileUploadForm(forms.Form):
    """多文件上传表单"""

    files = MultipleFileField(
        widget=MultipleFileInput(
            attrs={"accept": ".py,.js,.ts,.lua", "class": "form-control"}
        ),
        help_text="支持多文件或game文件夹选择，仅支持Python、JavaScript、TypeScript、Lua文件",
        required=True,
    )

    def clean(self):
        cleaned_data = super().clean()
        files = cleaned_data.get("files", [])

        # 确保files是列表
        if files and not isinstance(files, list):
            files = [files]

        if not files:
            raise forms.ValidationError("请至少上传一个文件")

        return cleaned_data

    def process_files(self, code_instance):
        """处理上传的文件并创建CodeFile实例"""
        created_files = []

        # 处理上传的文件
        files = self.cleaned_data.get("files", [])
        for file in files:
            created_files.extend(self._process_single_file(file, code_instance))

        # 注意：不再自动设置主文件，用户可以在文件管理页面手动设置

        return created_files

    def _process_single_file(self, file, code_instance):
        """处理单个文件，支持文件夹结构"""
        try:
            content = file.read().decode("utf-8")
        except UnicodeDecodeError:
            raise forms.ValidationError(f"文件 {file.name} 不是有效的文本文件")

        # 获取文件路径，支持相对路径（文件夹结构）
        file_path = (
            getattr(file, "relativePath", "") + file.name
            if hasattr(file, "relativePath")
            else file.name
        )

        # 规范化路径
        file_path = file_path.replace("\\", "/").strip("/")

        # 创建或更新CodeFile实例
        code_file, created = CodeFile.objects.get_or_create(
            code=code_instance,
            file_path=file_path,
            defaults={
                "content": content,
                "file_name": os.path.basename(file_path),
                "file_size": len(content.encode("utf-8")),
            },
        )
        if not created:
            # 如果文件已存在，更新内容
            code_file.content = content
            code_file.file_size = len(content.encode("utf-8"))
            code_file.save()

        return [code_file]


class CodeFileForm(forms.ModelForm):
    """单个代码文件表单"""

    class Meta:
        model = CodeFile
        fields = ["file_path", "content", "is_main"]
        widgets = {
            "file_path": forms.TextInput(
                attrs={"class": "form-control", "placeholder": "例如: src/main.py"}
            ),
            "content": forms.Textarea(
                attrs={
                    "class": "code-editor form-control",
                    "rows": 20,
                    "spellcheck": "false",
                }
            ),
            "is_main": forms.CheckboxInput(attrs={"class": "form-check-input"}),
        }

    def clean_file_path(self):
        file_path = self.cleaned_data.get("file_path")
        if not file_path:
            raise forms.ValidationError("文件路径不能为空")

        # 规范化路径
        file_path = file_path.replace("\\", "/").strip("/")

        # 检查路径安全性
        if ".." in file_path or file_path.startswith("/"):
            raise forms.ValidationError("文件路径不安全")

        return file_path
